﻿using System.Security.Cryptography.X509Certificates;

namespace Devonline.Security;

/// <summary>
/// 数据安全服务
/// 提供对数据的加密解密
/// </summary>
public class DataSecurityService(SecuritySetting securitySetting) : SecurityService(securitySetting), IDataSecurityService, ISecurityService
{
    //protected readonly IAsymmetricSecurityService _asymmetricSecurityService = new SM2SecurityService(securitySetting);
    protected readonly ISymmetricSecurityService _symmetricSecurityService = new AesSecurityService(securitySetting);
    protected readonly CertificateSecurityService _certificateSecurityService = new CertificateSecurityService(securitySetting);
    protected readonly X509Certificate2? _certificate = securitySetting.Certificate;

    /// <summary>
    /// 使用 RSA 证书公钥和自动 Aes 密码加密数据 data
    /// </summary>
    /// <param name="certificate">加密用的证书</param>
    /// <param name="data">待加密的数据明文</param>
    /// <returns>携带 Aes 密钥信息的加密后的数据密文</returns>
    public async Task<byte[]> EncryptAsync(X509Certificate2 certificate, byte[] data)
    {
        var keyIV = _symmetricSecurityService.GetKeyIV();
        var encrypted = await _symmetricSecurityService.EncryptAsync(keyIV.Key, keyIV.IV, data);
        KeyData keyData;
        if (keyIV.UsedCount == AppSettings.UNIT_ZERO)
        {
            var aesKey = await _certificateSecurityService.EncryptAsync(certificate, keyIV.Key);
            keyData = new KeyData(new KeyIV(keyIV.Id, aesKey, keyIV.IV), encrypted);
        }
        else
        {
            keyData = new KeyData(keyIV.Id, encrypted);
        }

        keyIV.Used();
        return keyData.Value;
    }
    /// <summary>
    /// 使用 RSA 证书私钥解密数据 data
    /// </summary>
    /// <param name="certificate">解密用的证书</param>
    /// <param name="data">携带 Aes 密钥信息的待解密的数据密文</param>
    /// <returns>解密后的数据明文</returns>
    public async Task<byte[]> DecryptAsync(X509Certificate2 certificate, byte[] data)
    {
        var keyData = new KeyData(data);
        KeyIV keyIV;
        if (keyData.EncryptionMode == DataEncryptionMode.KeyIV)
        {
            var encryptedKeyIV = keyData.KeyIV!;
            var aesKey = await _certificateSecurityService.DecryptAsync(certificate, encryptedKeyIV.Key);
            keyIV = new KeyIV(encryptedKeyIV.Id, aesKey, encryptedKeyIV.IV);
            _symmetricSecurityService.SetKeyIV(keyIV.Id, keyIV);
        }
        else
        {
            keyIV = _symmetricSecurityService.GetKeyIV(keyData.KeyId);
        }

        return await _symmetricSecurityService.DecryptAsync(keyIV.Key, keyIV.IV, keyData.Data);
    }

    /// <summary>
    /// 使用默认证书和一次性 Aes 密钥加密明文数据
    /// </summary>
    /// <param name="data">明文数据</param>
    /// <returns>加密后的数据, 数据中包含了 Aes 密钥信息</returns>
    public override async Task<byte[]> EncryptAsync(byte[] data)
    {
        if (_certificate is null)
        {
            throw new KeyNotFoundException("encrypt certificate not exist!");
        }

        return await EncryptAsync(_certificate, data);
    }
    /// <summary>
    /// 使用默认证书和密文数据携带的一次性 Aes 密钥解密密文数据
    /// </summary>
    /// <param name="data">密文数据</param>
    /// <returns>解密后的数据</returns>
    public override async Task<byte[]> DecryptAsync(byte[] data)
    {
        if (_certificate is null)
        {
            throw new KeyNotFoundException("decrypt certificate not exist!");
        }

        return await DecryptAsync(_certificate, data);
    }
}